package cn.wolfcode.business.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;

import cn.wolfcode.common.utils.file.FileUploadUtils;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.wolfcode.business.mapper.BusBpmnInfoMapper;
import cn.wolfcode.business.domain.BusBpmnInfo;
import cn.wolfcode.business.service.IBusBpmnInfoService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

/**
 * 流程定义明细Service业务层处理
 * 
 * @author wolfcode
 * @date 2025-04-09
 */
@Service
public class BusBpmnInfoServiceImpl implements IBusBpmnInfoService 
{
    @Autowired
    private BusBpmnInfoMapper busBpmnInfoMapper;

    @Autowired
    private RepositoryService repositoryService;

    /**
     * 查询流程定义明细
     * 
     * @param id 流程定义明细主键
     * @return 流程定义明细
     */
    @Override
    public BusBpmnInfo selectBusBpmnInfoById(Long id)
    {
        return busBpmnInfoMapper.selectBusBpmnInfoById(id);
    }

    /**
     * 查询流程定义明细列表
     * 
     * @param busBpmnInfo 流程定义明细
     * @return 流程定义明细
     */
    @Override
    public List<BusBpmnInfo> selectBusBpmnInfoList(BusBpmnInfo busBpmnInfo)
    {
        return busBpmnInfoMapper.selectBusBpmnInfoList(busBpmnInfo);
    }

    /**
     * 新增流程定义明细
     * 
     * @param busBpmnInfo 流程定义明细
     * @return 结果
     */
    @Override
    public int insertBusBpmnInfo(BusBpmnInfo busBpmnInfo)
    {
        return busBpmnInfoMapper.insertBusBpmnInfo(busBpmnInfo);
    }

    /**
     * 修改流程定义明细
     * 
     * @param busBpmnInfo 流程定义明细
     * @return 结果
     */
    @Override
    public int updateBusBpmnInfo(BusBpmnInfo busBpmnInfo)
    {
        return busBpmnInfoMapper.updateBusBpmnInfo(busBpmnInfo);
    }

    /**
     * 批量删除流程定义明细
     * 
     * @param ids 需要删除的流程定义明细主键
     * @return 结果
     */
    @Override
    public int deleteBusBpmnInfoByIds(Long[] ids)
    {
        return busBpmnInfoMapper.deleteBusBpmnInfoByIds(ids);
    }

    /**
     * 删除流程定义明细信息
     * 
     * @param id 流程定义明细主键
     * @return 结果
     */
    @Override
    public int deleteBusBpmnInfoById(Long id)
    {
        return busBpmnInfoMapper.deleteBusBpmnInfoById(id);
    }


    @Override
    @Transactional
    public int deploy(MultipartFile file, String bpmnLabel, Long bpmnType, String info) throws IOException {
        //安全性判定
        if(file == null || bpmnLabel == null || bpmnType == null || info == null){
            throw new RuntimeException("非法参数");
        }
        //文件类型验证 根据文件后缀名校验
        String extension = FileUploadUtils.getExtension(file);
        if(!("xml".equalsIgnoreCase(extension) || "bpmn".equalsIgnoreCase(extension))){
            throw new RuntimeException("上传文件类型必须是xml或bpmn格式的文件");
        }
        //流程定义部署 获取到部署对象
        Deployment deploy = repositoryService.createDeployment().addInputStream(file.getOriginalFilename(), file.getInputStream()).deploy();
        //根据部署对象获取流程定义对象 进而获取到key和version
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).latestVersion().singleResult();
        //向业务表中插入数据
        BusBpmnInfo busBpmnInfo = new BusBpmnInfo();
        //封装前台传递的三个数据
        busBpmnInfo.setBpmnLabel(file.getOriginalFilename());//流程名称
        busBpmnInfo.setBpmnType(bpmnType);//流程类型
        busBpmnInfo.setInfo(info);//流程备注
        //通过部署对象设置部署时间
        busBpmnInfo.setDeployTime(deploy.getDeploymentTime());
        //通过流程定义对象封装key和version
        busBpmnInfo.setProcessDefinitionKey(processDefinition.getKey());
        busBpmnInfo.setVersion(processDefinition.getVersion());
        return busBpmnInfoMapper.insertBusBpmnInfo(busBpmnInfo);
    }

    /*查看流程资源*/
    @Override
    public InputStream readResource(Long id, String type) {
        //参数合法性验证
        if(id == null || type == null){
            throw new RuntimeException("非法参数");
        }
        //通过id查询bpmnInfo对象
        BusBpmnInfo busBpmnInfo = this.selectBusBpmnInfoById(id);
        if(busBpmnInfo == null){
            throw new RuntimeException("非法参数");
        }
        //通过查询到的bpmnInfo对象获取到流程定义Key和version
        String processDefinitionKey = busBpmnInfo.getProcessDefinitionKey();
        Integer version = busBpmnInfo.getVersion();
        //通过获取到的Key和version查询到指定的流程定义
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processDefinitionKey).processDefinitionVersion(version).singleResult();
        if("xml".equalsIgnoreCase(type)){
            //查询xml文件
            //通过流程定义就可以获取到xml文件的文件名 和部署id
            String resourceName = processDefinition.getResourceName();//资源名称
            String deploymentId = processDefinition.getDeploymentId();//部署id
            //通过文件名就可以找到对应的xml文件的输入流
            InputStream xmlInputStream = repositoryService.getResourceAsStream(deploymentId, resourceName);
            return xmlInputStream;
        }else if("png".equalsIgnoreCase(type)){
            //读取png文件
            //需要使用activiti插件，可以根据xml文件来绘制图像
            DefaultProcessDiagramGenerator processDiagramGenerator = new DefaultProcessDiagramGenerator();
            //根据流程定义对象来获取model对象
            BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
            /*
            * 第一个参数：模型对象（有哪些节点、哪些连线、如何连线、坐标信息）
            * 第二个参数：高亮的节点
            * 第三个参数：高亮的连线
            * 第四五六个参数：使用什么字体来标识
            * */
            InputStream inputStream = processDiagramGenerator.generateDiagram(bpmnModel, Collections.emptyList(), Collections.emptyList(), "宋体", "宋体", "宋体");
            return inputStream;
        }

        return null;
    }

    /*撤销功能*/
    @Override
    @Transactional
    public int cancel(Long id) {
        //参数合理化验证
        if(id == null){
            throw new RuntimeException("非法参数");
        }
        BusBpmnInfo busBpmnInfo = this.selectBusBpmnInfoById(id);
        if(busBpmnInfo == null){
            throw new RuntimeException("非法参数");
        }
        //根据busBpmnInfo对象中的key和version查询流程定义对象
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(busBpmnInfo.getProcessDefinitionKey()).processDefinitionVersion(busBpmnInfo.getVersion()).singleResult();
        //删除该部署及其所有相关资源 级联删除(包括部署、流程定义、资源文件、当前正在运行的流程实例)
        repositoryService.deleteDeployment(processDefinition.getDeploymentId(),true);
        return busBpmnInfoMapper.deleteBusBpmnInfoById(id);
    }

    @Override
    public BusBpmnInfo selectBusBpmnInfoByTypeId(Integer type) {
        return busBpmnInfoMapper.selectBusBpmnInfoByTypeId(type);
    }
}
